#include <common.h>
#include <mmc.h>
#include <oem_inand.h>
#include <oem_func.h>
#include <asm/io.h>
#include <spi.h>
#include <spi_flash.h>

extern struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
		unsigned int max_hz, unsigned int spi_mode);
static void led_flash(void)
{
	u32 tmp0;
	tmp0 = readl(GPECON);
	tmp0 = (tmp0 &(~(3<<10))) | (1<<10);
	writel(tmp0,GPECON);
	writel(0,GPEPUD);
	
	tmp0 = readw(GPEDAT);
	if(tmp0 & (1<<5))tmp0 &= (~(1<<5));
	else tmp0 |= (1<<5);
	writew(tmp0,GPEDAT);
}
static void led_off(void)
{
	u32 tmp0;
	tmp0 = readw(GPEDAT);
	tmp0 |= (1<<5);
	writew(tmp0,GPEDAT);
}

int oem_erase_flash(int offset, int cnt)
{
	struct spi_flash *flash;
	
	spi_init();
	flash = spi_flash_probe(0,0,1000000,0);
	if(flash == NULL)
	{
		printf("spi_flash prone error.\n");
		return -1;
	}
	if(offset%flash->block_size) offset +=(flash->block_size-offset%flash->block_size);
	while(cnt >= flash->block_size)
	{
		led_flash();
		if(flash->erase(flash,offset,flash->block_size))
		{	
			printf("flash erase error.\n");
			return -1;
		}
		offset += flash->block_size;
		cnt -= flash->block_size;
	}
	if(flash->erase(flash,offset,flash->block_size))
	{	
		printf("flash erase error.\n");
		return -1;
	}
	led_off();
	printf("flash earse ok.\n");
	return 0;
}

int oem_write_flash(char *membase, int offset, int cnt)
{
	struct spi_flash *flash;
	int i,count;
	if(membase == NULL) 
 	{
		printf("Error: invalid image buffer address %x", (int)membase);
		return 1;
	}
	spi_init();
	flash = spi_flash_probe(0,0,1000000,0);
	if(flash == NULL)
	{
		printf("spi_flash prone error.\n");
		return -1;
	}
	if(offset%flash->block_size) offset +=(flash->block_size-offset%flash->block_size);
	count = flash->block_size/flash->page_size;
	while(cnt >= flash->block_size)
	{
		led_flash();
		if(flash->erase(flash,offset,flash->block_size))
		{	
			printf("flash erase error.\n");
			return -1;
		}
		for(i=0;i<count;i++)
		{
			if(flash->write(flash,offset,flash->page_size,membase))
			{	
				printf("flash write error.\n");
				return -1;
			}
			membase += flash->page_size;
			offset += flash->page_size;
		}
		cnt -= flash->block_size;
	}
	if(flash->erase(flash,offset,flash->block_size))
	{	
		printf("flash erase error.\n");
		return -1;
	}
	while(cnt > 0)
	{
		led_flash();
		if(flash->write(flash,offset,flash->page_size,membase))
		{	
			printf("flash write error.\n");
			return -1;
		}
		offset += flash->page_size;
		membase += flash->page_size;
		cnt -= flash->page_size;
	}
	led_off();
	printf("flash write ok.\n");
	return 0;
}

int oem_read_flash(char *membase, int offset, int cnt)
{
	struct spi_flash *flash;
	if(membase == NULL) 
 	{
		printf("Error: invalid image buffer address %x", (int)membase);
		return 1;
	}
	spi_init();
	flash = spi_flash_probe(0,0,1000000,0);
	if(flash == NULL)
	{	
		printf("spi_flash_probe\n");
		return -1;
	}
	led_flash();
	if(flash->read(flash,offset,cnt,membase))
	{	
		printf("flash read error.\n");
		led_off();
		return -1;
	}
	led_off();
	printf("flash read ok.\n");
	return 0;
}
